/**
  ******************************************************************************
  * @file    xxx.c 
  * @author  SD Electronics xxx
  * @version V1.0
  * @date    xx-xx-xx
  * @brief   xxxxxxxxxxxxxxxxxx.
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "sd_common.h"


/** 
  * @brief  BLE设备参数
  */ 
void app_gap_evt_cb(gap_event_t *p_event);

/** 
  * @brief  BLE设备参数
  */ 
uint8_t FactoryName[27];

/** 
  * @brief  BLE设备参数
  */ 
mac_addr_t dev_mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

/** 
  * @brief  BLE设备参数
  */ 
uint8_t adv_data[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

/** 
  * @brief  BLE设备参数
  */ 
gap_security_param_t param =
{
    .mitm = false,	// dont use PIN code during bonding
    .ble_secure_conn = false,	//not enable security encryption
    .io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT, //ble device has neither output nor input ability, 
    .pair_init_mode = GAP_PAIRING_MODE_WAIT_FOR_REQ,		//need bond
    .bond_auth = true,	//need bond auth
    .password = 0,
};

/** 
  * @brief  BLE设备参数结构体
  */ 
ST_BLE_CNT_PHY st_BLE_cnt_phy = {
    "Hi-DB_242TS-123FA00XXXX", 
    &dev_mac,
    adv_data,
    200,200,	//广播间隔
    36,36,		//连接间隔
    128,
    {0xB0, 0xFF},//service uuid
    {0xB1, 0xFF},//notify uuid
    {0xB2, 0xFF},//write uuid
    0,
    "00.00.01"
}; 

/** 
  * @brief  BLE控制结构体
  */ 
ST_BLE_CTRL g_stBLECtrl = 
{                       
    false,
    &st_BLE_cnt_phy,
};  
/**
  * @}
  */

/**
  * @brief  BLE app层事件回调函数
  * @note   包含：广播停止、服务add完成、从机连接完成等
  * @param  None
  * @retval None
  */
void app_gap_evt_cb(gap_event_t *p_event)
{
    switch(p_event->type)
    {
        case GAP_EVT_ADV_END:
        {
            co_printf("adv_end,status:0x%02x\r\n",p_event->param.adv_end.status);
            
        }
        break;
        
        case GAP_EVT_ALL_SVC_ADDED:
        {
            co_printf("All service added\r\n");
            
        }
        break;

        case GAP_EVT_SLAVE_CONNECT:
        {
            co_printf("slave[%d],connect. link_num:%d\r\n", p_event->param.slave_connect.conidx, gap_get_connect_num());
           
        }
        break;

        case GAP_EVT_DISCONNECT:
        {
            gap_start_advertising(0);
            co_printf("Link[%d] disconnect,reason:0x%02X\r\n",p_event->param.disconnect.conidx
                      ,p_event->param.disconnect.reason);
        }
        break;

        case GAP_EVT_LINK_PARAM_REJECT:
            co_printf("Link[%d]param reject,status:0x%02x\r\n"
                      ,p_event->param.link_reject.conidx,p_event->param.link_reject.status);
            break;

        case GAP_EVT_LINK_PARAM_UPDATE:
            co_printf("Link[%d]param update,interval:%d,latency:%d,timeout:%d\r\n",p_event->param.link_update.conidx
                      ,p_event->param.link_update.con_interval,p_event->param.link_update.con_latency,p_event->param.link_update.sup_to);
            break;

        case GAP_EVT_PEER_FEATURE:
            co_printf("peer[%d] feats ind\r\n",p_event->param.peer_feature.conidx);
          
            break;

        case GAP_EVT_MTU:
            co_printf("mtu update,conidx=%d,mtu=%d\r\n"
                      ,p_event->param.mtu.conidx,p_event->param.mtu.value);
            break;
        
        case GAP_EVT_LINK_RSSI:
            co_printf("link rssi %d\r\n",p_event->param.link_rssi);
            break;
                
        case GAP_SEC_EVT_SLAVE_ENCRYPT:
            co_printf("slave[%d]_encrypted\r\n",p_event->param.slave_encrypt_conidx);
				
            break;

        default:
            break;
    }
}


/**
  * @brief  sd_set_adv_data
  * @param  None
  * @note	xxx
  * @retval None
  */
void sd_set_adv_data(PST_BLE_CNT_PHY pstBLECntPhy, uint8_t *adv_data, uint32_t adv_data_len)
{
//--------------------------------Set advertising parameters----------------------
    gap_adv_param_t adv_param;
    adv_param.adv_mode = GAP_ADV_MODE_UNDIRECT;
    adv_param.adv_addr_type = GAP_ADDR_TYPE_PUBLIC;
    adv_param.adv_chnl_map = GAP_ADV_CHAN_ALL;
    adv_param.adv_filt_policy = GAP_ADV_ALLOW_SCAN_ANY_CON_ANY;
    adv_param.adv_intv_min = pstBLECntPhy->adv_int_MIN;
    adv_param.adv_intv_max = pstBLECntPhy->adv_int_MAX;
    gap_set_advertising_param(&adv_param);
//----------------------------------adv data-------------------------------------
    memcpy(pstBLECntPhy->adv_data, adv_data, adv_data_len);
    uint8_t *adv_pos;
    uint8_t local_adv_data[0x1C];
    adv_pos = local_adv_data;

    //UUID的数据广播
    uint16_t uuid_value = BUILD_UINT16(pstBLECntPhy->service_uuid[0], pstBLECntPhy->service_uuid[1]);
    *adv_pos++ = sizeof(uuid_value) + 1;
    *adv_pos++ = GAP_ADVTYPE_16BIT_COMPLETE;
    memcpy(adv_pos, (uint8_t *)&uuid_value, sizeof(uuid_value));
    adv_pos += sizeof(uuid_value);

    //Specific数据
    *adv_pos++ = adv_data_len + 1;
    *adv_pos++  = GAP_ADVTYPE_MANUFACTURER_SPECIFIC;
    memcpy(adv_pos, pstBLECntPhy->adv_data, adv_data_len);
    adv_pos += adv_data_len;
    
    //数据长度的计算
    adv_data_len = ((uint32_t)adv_pos - (uint32_t)(&local_adv_data[0]));
    gap_set_advertising_data(local_adv_data, adv_data_len);
//---------------------------------rsp data---------------------------------------
    uint8_t *rsp_pos;
    uint8_t scan_rsp_data[0x1F];
    uint8_t scan_rsp_data_len = 0;

    uint8_t local_name[LOCAL_NAME_MAX_LEN];
    uint8_t local_name_len = gap_get_dev_name(local_name);

    rsp_pos = &scan_rsp_data[0];
    *rsp_pos++ = local_name_len + 1;                            //pos len;  (payload + type)
    *rsp_pos++  = GAP_ADVTYPE_LOCAL_NAME_COMPLETE;              //pos: type
    memcpy(rsp_pos, local_name, local_name_len);
    rsp_pos += local_name_len;
    scan_rsp_data_len = ((uint32_t)rsp_pos - (uint32_t)(&scan_rsp_data[0]));
    gap_set_advertising_rsp_data(scan_rsp_data, scan_rsp_data_len);
//---------------------------------start advtising---------------------------------
    gap_start_advertising(0);
}

/** 
  * 函数功能： 串口打开(串口的初始化)
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
void SDInitBLE(PST_BLE_CNT_PHY pstBLECntPhy)
{
    //MAC地址设置
    mac_addr_t addr;
    gap_address_get(&addr);
    co_printf("MAC:[%02X %02X %02X %02X %02X %02X]\r\n", addr.addr[0], addr.addr[1], 
    addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5]);
    memcpy(pstBLECntPhy->addr, addr.addr, MAC_ADDR_LEN);

    //名字设置
    sprintf((char *)FactoryName, "Hi-DB_242TS-123FA00%02X%02X", addr.addr[4], addr.addr[5]);
    gap_set_dev_name(FactoryName, sizeof("Hi-DB_242TS-123FA00XXXX"));
    memcpy(pstBLECntPhy->ble_name, FactoryName, sizeof("Hi-DB_242TS-123FA00XXXX"));

    gap_security_param_init(&param);
    gap_set_cb_func(app_gap_evt_cb);
    gap_bond_manager_init(BLE_BONDING_INFO_SAVE_ADDR, BLE_REMOTE_SERVICE_SAVE_ADDR, 8, true);
    gap_address_set(pstBLECntPhy->addr);

	//设置广播参数-----------默认设置MAC地址
    sd_set_adv_data(pstBLECntPhy, pstBLECntPhy->addr->addr, MAC_ADDR_LEN);
    //添加相应BLE服务
    SDAT_gatt_add_service(NULL, pstBLECntPhy);
    //SDFBL_gatt_add_service(NULL, pstBLECntPhy);
    //添加OTA服务
    ota_gatt_add_service();
    //添加其他服务
    
    printf("usr: sd BLE init.\r\n");
}

/** 
  * 函数功能： 串口打开(串口的初始化)
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
static long BLEOpen(void *pvHandle, unsigned long ulOption)
{
    PST_DEV_MANAGE pstDevManage = pvHandle;

    long lRet = EN_DEV_CTL_RET_CODE_FAILED;
    if (0 != pstDevManage)
    {
        PST_BLE_CTRL pstBLECtrl = (PST_BLE_CTRL)pstDevManage->pvData;
        if(false == pstBLECtrl->bInitFlag)
        {
			/* BLE驱动初始化----这里添加串口的初始化函数 */
            SDInitBLE(pstBLECtrl->pstBLEInfo);
            pstBLECtrl->bInitFlag = true;
        }
        lRet = EN_DEV_CTL_RET_CODE_SUCCESSED;
    }
    return lRet;
}  

/** 
  * 函数功能： 串口读
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
static long BLERead(void *pvHandle, unsigned long ulOpertion, unsigned char *pucDataBuf, int* ulDataSize)
{
    PST_DEV_MANAGE pstDevManage = pvHandle;
    long lRet = EN_DEV_CTL_RET_CODE_FAILED;
    if (0 != pstDevManage)
    {
        PST_BLE_CTRL pstBLECtrl = (PST_BLE_CTRL)pstDevManage->pvData;
        /* 已经完成初始化 */
        if(true == pstBLECtrl->bInitFlag)
        {
            switch(ulOpertion)
            {
                case CMD_NAME:
                {
                    printf("usr: %s: %d.\r\n",__func__, __LINE__);
                    *ulDataSize = strlen((char*)pstBLECtrl->pstBLEInfo->ble_name);
                    memcpy(pucDataBuf, pstBLECtrl->pstBLEInfo->ble_name, *ulDataSize);
                    break;
                }
                
                case CMD_MAC:
                {
                    printf("usr: %s: %d.\r\n",__func__, __LINE__);
                    *ulDataSize = MAC_ADDR_LEN*2;
                    memcpy(pucDataBuf, hex_to_str(pstBLECtrl->pstBLEInfo->addr->addr, MAC_ADDR_LEN), *ulDataSize);
                    break;  
                }
                case CMD_BAUD:
                {
                    printf("usr: %s: %d.\r\n",__func__, __LINE__);
                    SDDevManageRead(EN_DEV_USART, 0, pucDataBuf, ulDataSize);
                    break;
                }

                case CMD_VER:
                {
                    printf("usr: %s: %d.\r\n",__func__, __LINE__);
                    *ulDataSize = strlen((char*)pstBLECtrl->pstBLEInfo->FirmwareVersion);
                    memcpy(pucDataBuf, pstBLECtrl->pstBLEInfo->FirmwareVersion, *ulDataSize);
                    break;
                }

                case CMD_PIN:
                {
                    printf("usr: %s: %d.\r\n",__func__, __LINE__);
                    char local_pin[0x06] = {0};
                    /* 此处没有使用sprintf,有问题未找到原因 */
                    co_sprintf((char*)local_pin, "%d", pstBLECtrl->pstBLEInfo->pincode);
                    *ulDataSize = strlen((char *)local_pin);
                    memcpy(pucDataBuf, local_pin, *ulDataSize);
                    break;
                }

                case CMD_MODE:
                break;

                /* 透传模式 */
                case CMD_TPMODE:
                    SDDevManageWrite(EN_DEV_USART, CMD_TPMODE, pucDataBuf, *ulDataSize);    
                break;

                /* 重启 */
                case CMD_REBOOT:
                {
                    //nothing to do     
                }
                break;

                /* 恢复出厂设置 */
                case CMD_RESTORE:
                {

                }
                break;
            
                default:lRet = EN_DEV_CTL_RET_CODE_FAILED;break;
            }
        }
        lRet = EN_DEV_CTL_RET_CODE_SUCCESSED;
    }
    return lRet;    
}

/** 
  * 函数功能： 串口写
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
static long BLEWrite(void *pvHandle, unsigned long ulOpertion, unsigned char *pucDataBuf, unsigned long ulDataLen)
{
    PST_DEV_MANAGE pstDevManage = pvHandle;
    long lRet = EN_DEV_CTL_RET_CODE_FAILED;
    if (0 != pstDevManage)
    {
        PST_BLE_CTRL pstBLECtrl = (PST_BLE_CTRL)pstDevManage->pvData;
        /* 已经完成初始化 */
        if(true == pstBLECtrl->bInitFlag)
        {
           
        }
        
    }
    return lRet;
}

/** 
  * 函数功能： 串口控制
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
static long BLEControl (void *pvHandle,unsigned long ulOpertion, unsigned long ulControlCmd, void *pvd)
{
    PST_DEV_MANAGE pstDevManage = pvHandle;
    long lRet = EN_DEV_CTL_RET_CODE_FAILED;
    if (0 != pstDevManage)
    {
        lRet = EN_DEV_CTL_RET_CODE_SUCCESSED;
    }
    return lRet;             
}

/** 
  * 函数功能： 串口关闭
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
static long BLEClose (void *pvHandle)
{
    PST_DEV_MANAGE pstDevManage = pvHandle;
    long lRet = EN_DEV_CTL_RET_CODE_FAILED;
    if (0 != pstDevManage)
    {
        PST_BLE_CTRL pstBLECtrl = (PST_BLE_CTRL)pstDevManage->pvData;
        if(0 != pstBLECtrl)
        {
            pstBLECtrl->bInitFlag = false;
        }
        lRet = EN_DEV_CTL_RET_CODE_SUCCESSED;
    }
    return lRet;    
}



/** 
  * 函数功能： BLE控制管理回调函数
  * 参数说明：
  * 返回说明：
  * 调用范围：
  * 完成时间：
  * 修改时间：
  * 修改原因：
  */
ST_CTR_FUN g_stBLECtlFUN = 
{
    BLEOpen,		/* 打开---用于初始化设备管理的时候调用 */
    BLERead,		/* 读 */
    BLEWrite,		/* 写 */
    BLEControl,		/* undefine */
    BLEClose    	/* 关闭 */
};




/******************* (C) COPYRIGHT 2011 ShenZhenShiding electronics **************************/
